<?php
/*
 * Copyright (c) 2021.  Liuhongbin All rights reserved.
 * @domain http://dkyx.cc
 * @author liuhongbin <514660094@qq.com>
 */

namespace app\controller\adminapi\platform;

use app\common\model\addon\Addons;
use app\common\model\platform\Platform;
use app\common\model\platform\PlatformApp as PlatformAppModel;
use app\common\model\platform\PlatformAppUser;
use app\common\model\user\User;
use app\common\model\user\UserPermission;
use app\common\model\wework\WeworkApps;
use FormBuilder\Driver\CustomComponent;
use FormBuilder\Driver\FormComponent;
use hiduoke\services\CloudServer;
use hiduoke\services\douyinMinApp\DouyinMinApp;
use hiduoke\services\douyinMinApp\DouyinMinAppServer;
use hiduoke\services\FormBuilder as Form;
use think\App;
use think\facade\Cache;

/**
 * 平台应用小程序
 */
class PlatformApp extends PlatformController
{
    /**
     * @var PlatformAppModel
     */
    private PlatformAppModel $model;

    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->model = new PlatformAppModel();
    }

    /**
     * 获取小程序信息
     * @param $plaid
     * @param $appid
     * @return \think\response\Json
     */
    public function appInfo($plaid = 0, $appid = 0)
    {
        $plaid = $plaid ?: get_plaid();
        $appid = $appid ?: get_appid();
        $res = $this->model->where(['plaid' => $plaid, 'id' => $appid])->find();
        if (!$res) {
            return $this->error('未找到当前小程序');
        }
        $addon = (new Addons())->where(['name' => $res['addon_name']])->find();
        if ($res['logo']) {
            $addon['icon'] = $res['logo'];
        }
        if ($res['name']) {
            $addon['title'] = $res['name'];
        }
        return $this->success('', $addon);
    }

    public function getPlatformAppList()
    {
        $refresh = input('refresh', null);
        if ($refresh) {
            Cache::tag('dy_version_' . get_plaid())->clear();
        }
        $user = get_user();
        $platform = Platform::where(['plaid' => get_plaid()])->find();
        if (!$platform) {
            return $this->error("平台有误");
        }
        $where = [];
        if (!$user['is_admin'] && $platform['uid'] != $user['uid']) {
            // 如果不是管理员，而是子账号
            $addon_names = (new UserPermission())->getAddonNames($user['uid'], $platform['plaid']);
            $where = [['addon_name', 'in', $addon_names]];
        }
        $append = ['addon'];
        $data = $this->model->dkWhere($where)->getPageListModel()->append($append)->withSearch(['addon'])->select();
        $multiCurl = curl_multi_init();
        $curlHandles = [];
        $promises = [];
        if ($refresh !== null) {
            foreach ($data as $key => $value) {
                try {
                    $DouyinMinApp = new DouyinMinApp($value['id']);
                } catch (\Exception $e) {
                    continue;
                }
                if ($DouyinMinApp->getAuthType() == 0) {
                    continue;
                }
                $DY = $DouyinMinApp->DYServer;
                $component_appid = $DY->config['component_appid'];
                $authorizer_access_token = $DY->get_authorizer_access_token();
                // 创建 cURL 句柄
                $curlHandles[$key] = curl_init();
                $url = "https://open.microapp.bytedance.com/openapi/v1/microapp/package/versions?" . http_build_query([
                        'component_appid'         => $component_appid,
                        'authorizer_access_token' => $authorizer_access_token
                    ]);
                curl_setopt($curlHandles[$key], CURLOPT_URL, $url);
                curl_setopt($curlHandles[$key], CURLOPT_RETURNTRANSFER, true);
                curl_setopt($curlHandles[$key], CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
                // 添加到多重处理
                curl_multi_add_handle($multiCurl, $curlHandles[$key]);
                // 保存 promise 以便后续处理
                $promises[$key] = $curlHandles[$key];
            }
            // 执行多重处理
            $running = null;
            do {
                curl_multi_exec($multiCurl, $running);
                curl_multi_select($multiCurl);
            } while ($running > 0);
            // 获取每个请求的结果并记录执行时间
            foreach ($promises as $key => $ch) {
                $response = curl_multi_getcontent($ch);
                if ($response === false) {
                    $data[$key]['versions'] = null;
                } else {
                    $data[$key]['versions'] = json_decode($response, true)['data'] ?? false;
                    if ($data[$key]['versions']) {
                        $data[$key]->save(['versions' => $data[$key]['versions']]);
                    }
                }
                // 移除并关闭 cURL 句柄
                curl_multi_remove_handle($multiCurl, $ch);
                curl_close($ch);
            }
            // 关闭多重处理
            curl_multi_close($multiCurl);
        }
        $count = $this->model->dkWhere($where)->getPageListModel([], false)->append(['addon'])->withSearch(['addon'])->count();

        foreach ($data as $key => $value) {
            $data[$key]['isDefault'] = false;
            if ($platform['default_app_id'] == $value['id']) {
                $data[$key]['isDefault'] = true;
            }
        }
        return $this->success($count, $data);
    }

    /**
     * 批量上线小程序
     * Create by :  刘泓宾<514660094@qq.com>
     */
    public function releasePlatformAppList()
    {
        $plaid = get_plaid();
        $apps = (new PlatformAppModel())->where(['plaid' => $plaid])->select();
        $multiCurl = curl_multi_init();
        $curlHandles = [];
        $promises = [];
        foreach ($apps as $key => $value) {
            $DY = new DouyinMinAppServer($value['id']);
            $component_appid = $DY->config['component_appid'];
            $authorizer_access_token = $DY->get_authorizer_access_token();
            // 创建 cURL 句柄
            $curlHandles[$key] = curl_init();
            $url = "https://open.microapp.bytedance.com/openapi/v1/microapp/package/release?" . http_build_query([
                    'component_appid'         => $component_appid,
                    'authorizer_access_token' => $authorizer_access_token
                ]);
            curl_setopt($curlHandles[$key], CURLOPT_URL, $url);
            curl_setopt($curlHandles[$key], CURLOPT_POST, true); // 设置为POST请求
            curl_setopt($curlHandles[$key], CURLOPT_RETURNTRANSFER, true);
            curl_setopt($curlHandles[$key], CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
            // 添加到多重处理
            curl_multi_add_handle($multiCurl, $curlHandles[$key]);
            // 保存 promise 以便后续处理
            $promises[$key] = $curlHandles[$key];
        }
        $count = 0;
        $err_count = 0;
        // 执行多重处理
        $running = null;
        do {
            curl_multi_exec($multiCurl, $running);
            curl_multi_select($multiCurl);
        } while ($running > 0);
        // 获取每个请求的结果并记录执行时间
        foreach ($promises as $key => $ch) {
            $response = curl_multi_getcontent($ch);
            if ($response === false) {
                $err_count++;
            } else {
                $res = json_decode($response, true);
                if ($res['errno'] == 0) {
                    $count++;
                } else {
                    $err_count++;
                }
            }
            // 移除并关闭 cURL 句柄
            curl_multi_remove_handle($multiCurl, $ch);
            curl_close($ch);
        }
        // 关闭多重处理
        curl_multi_close($multiCurl);
        return $this->success("批量上线成功" . $count . "个失败 " . $err_count . "个");
    }


    /**
     * 添加应用小程序
     * @param $aid
     * @param $addon_name
     * @param $plaid
     */
    public function addPlatformAddonApp($aid, $addon_name, $plaid)
    {
        $platform = (new Platform())->where(['plaid' => $plaid])->find();
        if (!$platform) {
            return $this->error('平台不存在');
        }
        $addon = (new Addons())->where(['name' => $addon_name])->find();
        if (!$addon) {
            return $this->error('应用不存在');
        }
        // 已使用次数
        $platform_app_count = $this->model->where(['aid' => $aid, 'addon_name' => $addon_name, 'plaid' => $plaid])->count();
        // 总次数
        $platform_app_user = (new PlatformAppUser())->where(['addon_name' => $addon_name, 'uid' => $platform['uid']])->find();

        if (!$platform_app_user || $platform_app_user['count'] <= $platform_app_count) {
            return $this->error('当前应用可添加次数不足');
        }
        // 获取平台信息
        $cloud_data = (new CloudServer())->getSiteAddonTokenCount(false);
        if (isset($cloud_data[$addon_name]) && $cloud_data[$addon_name]['surplus_count'] <= 0) {
            return $this->error("添加失败，应用token授权次数不足");
        }
        $token_res = (new CloudServer())->getSiteAddonToken($addon_name, $plaid, true);
        // 判断小程序次数
        if ($token_res['code'] == -1) {
            // 应用无法添加
            return $this->error($token_res['msg']);
        } else {
            if ($token_res['code'] == -2) {
                // 本地应用
                $token = 'local';
            } else {
                // 线上应用
                if (isset($token_res['data']['token'])) {
                    $token = $token_res['data']['token'];
                } else {
                    return $this->error("添加失败，token授权失败");
                }
            }
            $app_data = array(
                'uid'        => $platform['uid'],
                'aid'        => $aid,
                'plaid'      => $plaid,
                'addon_name' => $addon_name,
                'app_type'   => $addon['app_type'],
                'token'      => $token
            );
            $this->model->save($app_data);
            (new Platform())->where(['plaid' => $plaid])->update(['default_app_id' => $this->model->id]);
            Cache::delete('getSiteAddonTokenCount2');
            return $this->success('添加成功');
        }
    }

    public function getPlatformAddonAppForm()
    {
        $id = input("id", 0);
        $action = "/adminapi/platform/app/platformAddonAppFormSave";
        $platform = (new Platform())->where(['plaid' => get_plaid()])->find();
        if (!$platform) {
            return $this->error('平台不存在');
        }
        if (!$id) {
            $id = $this->model->where(['plaid' => get_plaid(), 'addon_name' => get_addon()])->value('id');
        }
        $rule = array();
        $form = Form::createForm($action)->setMethod("POST");
        $row = $this->model->where(['id' => $id])->findOrEmpty();
        $col = Form::col()->span(11)->offset(1)->pull(1);
        $rule[] = Form::hidden('id', $row->id);
        $rule[] = Form::switches('index', '首页显示', strval($row->index))->col($col)->effect(['help' => '显示到客户端首页']);
        $rule[] = Form::switches('menu', '菜单显示', strval($row->menu))->col($col)->effect(['help' => '显示到平台左侧列表页']);
        $rule[] = Form::dkImage('logo', '图标', $row['logo'] ?? '')->effect(['help' => '自定义小程序图标,方便区分']);
        $rule[] = Form::input('name', '名称', $row['name'] ?? '')->effect(['help' => '自定义小程序名称,方便区分']);
        $rule[] = Form::input('remark', '备注', $row['remark'] ?? '')->effect(['help' => '设置备注信息']);
        $rule[] = Form::input('sort', '排序', $row['sort']);
        if ($this->userInfo['is_admin']) {
            $rule[] = Form::input('token', 'Token', $row['token'] ?? '')->effect(['help' => '小程序应用秘钥，仅管理员可见，对应怪兽商城授权token'])->disabled(true);
        }
        if (input('is_admin', 0) && $this->userInfo['is_admin']) {
            $rule[] = Form::input('token', "应用Token", $row['token'] ?? '')->effect(['help' => '平台下的应用Token，请勿随意修改，可能会导致应用部分云端功能无法使用,仅管理员可见']);
        }
        $addon_rules = event($row['addon_name'] . '_platform_addon_config', $row['config'])[0] ?? [];
        if (!$addon_rules) {
            $instance = get_addons_instance($row['addon_name']);
            if ($instance !== null && method_exists($instance, 'platform_addon_config')) {
                $addon_rules = $instance->platform_addon_config($row['config']);
            }
        }
        if (is_array($addon_rules)) {
            foreach ($addon_rules as $key => $value) {
                if ($value instanceof FormComponent) {
                    $rule[] = $value;
                } elseif ($value instanceof CustomComponent) {
                    $rule[] = (new CustomComponent('elCol'))->appendChild($value)->props(['style' => 'margin-bottom:22px']);
                }
            }
        }
        $form->setTitle("平台应用小程序配置")->setRule($rule);
        return $this->success("", Form::getFormData($form));
    }

    public function platformAddonAppFormSave($formData = [])
    {
        $id = $formData['id'];
        $res = $this->model->where(['id' => $id])->find();
        if ($res) {
            $res->index = $formData['index'];
            $res->menu = $formData['menu'];
            $res->sort = $formData['sort'];
            $res->logo = $formData['logo'];
            $res->name = $formData['name'];
            $res->remark = $formData['remark'];
            if (isset($formData['token'])) {
                $res->token = $formData['token'];
            }
            unset($formData['index']);
            unset($formData['menu']);
            unset($formData['sort']);
            unset($formData['logo']);
            unset($formData['name']);
            unset($formData['remark']);
            $res->config = $formData;
            $res->save();
            return $this->success("修改成功");
        } else {
            return $this->error('修改失败，未找到对应应用');
        }
    }
}
